package com.dhnsoft.数据结构与算法.栈与队列.栈;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Stack;

/**
 * ClassName: PolandNotation
 * Package: com.dhnsoft.数据结构与算法.栈与队列.栈
 * Description: 逆波兰表达式-后缀表达式
 *
 * @Author dhn
 * @Create 2024/3/26 12:54
 * @Version 1.0
 */
public class PolandNotation {

    public static void main(String[] args) {
//        String suffixExpression = "4 5 * 8 - 60 + 8 2 / +";
//        List<String> listString = getListString(suffixExpression);
        //中缀表达式
        String suffixExpression = "1+((2+3)*4)-5";
        List<String> listStringMid = getListStringMid(suffixExpression);
        System.out.println(listStringMid);
        //将中缀表达式改成后缀表达式
        List<String> suffixExpressionList = parseSuffixExpressionList(listStringMid);
        System.out.println(suffixExpressionList);
//        int calculate = calculate(listString);
//        System.out.println(calculate);
    }

    private static List<String> parseSuffixExpressionList(List<String> listStringMid) {
        Stack<String> s1 = new Stack<>();
        List<String> s2 = new ArrayList<>();
        for (String item : listStringMid) {
            if(item.matches("\\d+")){
                s2.add(item);
            }
            else if(item.equals("(")){
                s1.push(item);
            }
            else if(item.equals(")")){
                while (!s1.peek().equals("(")){
                    s2.add(s1.pop());
                }
                s1.pop();
            }
            else{
                 while (s1.size()!=0&&Operation.getValue(item)<=Operation.getValue(s1.peek())){
                    s2.add(s1.pop());
                }
                s1.push(item);
            }
        }
        //将s1中剩余的运算符依次弹出并加入s2
        while(s1.size()!=0){
            s2.add(s1.pop());
        }
        return s2;
    }



    /**
     * 拆分中缀表达式，将每一个部分装入list集合中
     * */

    public static List<String> getListStringMid(String suffixExpression){
        char[] chars = suffixExpression.toCharArray();
        List<String> ls = new ArrayList<>();
        int i=0;
        String str = null;
        while (i<chars.length){
            if((chars[i]<48)||(chars[i]>57)){
                ls.add(chars[i]+"");
                i++;
            }
            else{
                str = "";
                //考虑数是多位数
                while (i<chars.length&&(chars[i]>=48)&&(chars[i]<=57)){
                    str +=chars[i]+"";
                    i++;
                }
                ls.add(str);
            }
        }
        return ls;
    }


    //将一个逆波兰表达式，依次将数据和运算符放入到ArrayList中
    public static List<String> getListString(String suffixExpression){
        String[] strArr = suffixExpression.split(" ");
        List<String> list = new ArrayList<>();
        for (String s : strArr) {
            list.add(s);
        }
        return list;
    }

    public static int calculate(List<String> list){
        Stack<String> stack = new Stack<>();
        for (String item : list) {
            if(item.matches("\\d+")){
                stack.push(item);
            }
            else{
                int num2 = Integer.parseInt(stack.pop());
                int num1 = Integer.parseInt(stack.pop());
                int res = 0;
                if(Objects.equals(item,"+")){
                    res = num1+num2;
                }
                else if(Objects.equals(item,"-")){
                    res = num1-num2;
                }
                else if(Objects.equals(item,"*")){
                    res = num1*num2;
                }
                else if(Objects.equals(item,"/")){
                    res = num1/num2;
                }
                stack.push(res+"");
            }
        }
        return Integer.parseInt(stack.pop());
    }
}


class Operation{
    private static int ADD=1;
    private static int SUB=1;
    private static int MUL=2;
    private static int DIV=2;

    public static int getValue(String operation){
        int result = 0;
        switch (operation){
            case "+":
                result = ADD;
                break;
            case "-":
                result = SUB;
                break;
            case "*":
                result = MUL;
                break;
            case "/":
                result = DIV;
                break;
            default:
                System.out.println("不存在该运算符");
                break;
        }
        return result;
    }

}